import logging
from datetime import datetime, timedelta

import jwt
from django.core import serializers
from django.shortcuts import render
from django.utils.decorators import method_decorator
from django.http import HttpResponse
from django.views import View

from config import token_config
from utils.verifyUtil import verifyParam
from utils.resFormatUtil import ResFormat
from celery_tasks.email.tasks import send_email_task
from django_redis import get_redis_connection
from django.contrib.auth.hashers import make_password, check_password
from apps.user.models import User_info,UserDetail
import re, io, json
import random
from utils.verifyUtil import Imageverify
from fdfs_client.client import Fdfs_client,get_tracker_conf
from cyxmall.settings import FASTDFS_SERVER_DOMAIN

# Create your views here.
EMAIL_KEY = 'email:verification:%s'
LOGIN_KEY = 'login:verification:%s'


class EmailView(View):
    DURATION = 60  # 有效时长，单位秒

    @method_decorator(verifyParam('email'))
    def get(self, request):
        return HttpResponse('Ok')

    def post(self, request):
        email = request.POST.get('email')
        # 验证邮箱
        re_email = r'(\w+)@(\w+)\.(\w+)'
        if not re.match(re_email, email):
            return ResFormat(status='PARAM_ERROR').json_response()
        # 生成随机验证码
        verify_code = random.randint(100000, 999999)
        # 校验发送验证码是否已经过去了60s
        cache_default = get_redis_connection()
        if cache_default.get(email):
            return ResFormat(status='ACCESS_RESTRICTION').json_response()
        # 发送邮件
        # self.send_email_task(email,verification_code,self.DURATION)
        send_email_task.delay(email, verify_code, self.DURATION)
        # return HttpResponse('Ok')
        return ResFormat().json_response()


class RegisterView(View):
    @method_decorator(verifyParam('email', 'password', 'verify_code'))
    def post(self, request):
        post = request.POST
        email = post.get('email')
        password = make_password(post.get('password'))
        verify_code = post.get('verify_code')
        # 验证邮箱
        re_email = r'(\w+)@(\w+)\.(\w+)'
        if not re.match(re_email, email):
            return ResFormat(status='PARAM_ERROR').json_response()
        # 验证码校验
        cache = get_redis_connection(alias='verify_code')  # 获取Redis连接对象
        redis_verification = cache.get(EMAIL_KEY % email)
        if (not redis_verification) or (verify_code != redis_verification):
            return ResFormat(status='CODE_ERROR').json_response()
        # 及时释放空间
        cache.delete(EMAIL_KEY % email)
        # 用户是否注册过
        user_query = User_info.objects.filter(email=email)
        if user_query:
            return ResFormat(status='ACCOUNT_REGISTER').json_response()
        # 保存用户信息
        User_info.objects.create(email=email, password=password)
        return ResFormat().json_response()


class ImgverifyView(View):
    EXPIRE_TIME = 60 * 3

    def get(self, request, uuid):
        img, code = Imageverify().image_code()
        # 创建二进制管道
        bytes_box = io.BytesIO()
        # 将图片存入管道
        img.save(bytes_box, format='png')
        # 从管道获取二进制的值
        img_bytes = bytes_box.getvalue()
        # 保存code
        cache = get_redis_connection('verify_code')
        cache.set(LOGIN_KEY % uuid, code, self.EXPIRE_TIME)

        return HttpResponse(img_bytes, content_type='image/png')


class LoginView(View):

    @method_decorator(verifyParam('email', 'password', 'verify_code'))
    def post(self, request, uuid):
        post = request.POST
        email = post.get('email')
        password = post.get('password')
        verify_code = post.get('verify_code')

        # 校验验证码，不区分大小写
        cache = get_redis_connection(alias='verify_code')
        redis_verification = cache.get(LOGIN_KEY % uuid)  # 通过key取图片验证码的值

        if not redis_verification:  # redis库没有值
            return ResFormat(status='CODE_EXPIRED').json_response()  # 验证码过期

        if redis_verification.lower() != verify_code.lower():
            return ResFormat(status='CODE_ERROR').json_response()

        cache.delete(LOGIN_KEY % uuid)

        # 用户校验
        user = User_info.objects.filter(email=email)
        if not user:
            return ResFormat(status='PARAM_ERROR').json_response()

        if not check_password(password, user[0].password):  # 第一个明文，第二个加密
            return ResFormat(status='PASSWORD_ERROR').json_response()

        # 登录成功后，发放token
        payload = {
            'iss': 'LoginView_post',
            'sub': 'login',
            'iat': int(datetime.now().timestamp()),  # 签发时间
            # 'exp': int(datetime.now().timestamp()) + 60,  # 过期时间
            'exp': datetime.now()+timedelta(days=1), # 过期时间
            'email': email,
        }

        # token编码
        encode_jwt = jwt.encode(payload, token_config.TOKEN_SECRET_KEY, algorithm=token_config.ALG0RITHM,
                                headers=token_config.headers)

        return ResFormat(data=encode_jwt).json_response()


class DetailsView(View):

    def get(self, request):
        # # 获取token
        # authorization_token = request.META.get('HTTP_AUTHORIZATION')
        # # 1.判断是否有token
        # if not authorization_token:
        #     return ResFormat(status='ACCESS_RESTRICTION')
        # else:
        #     print(authorization_token)
        # # 解析token
        # try:
        #     decode_jwt = jwt.decode(authorization_token, token_config.TOKEN_SECRET_KEY, algorithms=token_config.ALG0RITHM)
        # # print(decode_jwt)
        # # 2.判断token是否过期
        # except jwt.exceptions.ExpiredSignatureError:
        #     return ResFormat(status='LOGIN_OUTTIME').json_response()
        # # 3.令牌是否正确
        # except jwt.exceptions.DecodeError:
        #     return ResFormat(status='PARAMS_ERROR').json_response()
        # # 4.其它错误
        # except Exception as e:
        #     return ResFormat(status='UNKNOWN_ERROR').json_response()

        # 5.从解析后的token获取用户信息data数据
        user_query = User_info.objects.get(email=request.email)
        # 6.构造个人信息
        try:
            user_detail = user_query.detail
        except:
            user_detail = UserDetail()
            user_detail.user = user_query
            user_detail.save()
        # user_detail 转成JSON serializable（json 序列化）
        # serialize--->'[{}]' ;loads---->[{}]
        user_detail = json.loads(serializers.serialize('json', [user_detail], ensure_ascii=False))
        data = {
            'email': user_query.email,
            'detail': user_detail[0]['fields'],
        }
        return ResFormat(data=data).json_response()

    def post(self,request):

        post = request.POST
        nickname = post.get('nickname')
        sex = post.get('sex')
        bth = post.get('bth')
        age = post.get('age')
        phone = post.get('phone')
        addr = post.get('addr')
        fav = post.get('fav')
        ps = post.get('ps')
        # 获取用户对象
        user = User_info.objects.get(email=request.email)
        # 反向查询用户详情
        try:
            user_detail = user.detail
        except:
            user_detail = UserDetail()
            user_detail.user = user
        # 保存信息
        user_detail.nickname = nickname
        user_detail.sex = sex
        user_detail.bth = bth
        user_detail.age = age
        user_detail.phone = phone
        user_detail.addr = addr
        user_detail.fav = fav
        user_detail.ps = ps
        user_detail.save()

        return ResFormat().json_response()

tracker_path = get_tracker_conf('utils/fastdfs/client.conf')
client = Fdfs_client(tracker_path)

logger = logging.getLogger(__name__)

class PortraitViews(View):

    def post(self,request):

        file = request.FILES.get('file')
        if not file or file.content_type not in ('image/jpg', 'image/jpeg', 'image/png'):
            return ResFormat(status='PARAM_ERROR').json_response()
        try:
            image_ext_name = file.name.split('.')[-1]
        except Exception as e:
            logger.error(f'图片后缀名错误：{e}')
            image_ext_name = 'png'

        try:
            res = client.upload_by_buffer(file.read(), file_ext_name=image_ext_name)
        except Exception as e:
            logger.error(f'图片上传异常{e}')
            return ResFormat(status='UPLOAD_EXCEPTION').json_response()
        else:
            if res.get('Status') != 'Upload successed.':
                return ResFormat(status='UPLOAD_EXCEPTION').json_response()
            else:
                img_url = FASTDFS_SERVER_DOMAIN + res.get('Remote file_id').decode()
                user = User_info.objects.get(email=request.email)
                try:
                    user_detail = user.detail
                except:
                    user_detail = UserDetail()
                    user_detail.user = user

                user_detail.portrait = img_url
                user_detail.save()

                return ResFormat(data=img_url).json_response()



